Skip to content

fix: set transfer amount to max on cap error#1013

Merged
ovitrif merged 7 commits into
masterfrom
fix/set-max-amount-transfer
Jun 15, 2026
Merged

fix: set transfer amount to max on cap error#1013
ovitrif merged 7 commits into
masterfrom
fix/set-max-amount-transfer

Conversation

@jvsena42

@jvsena42 jvsena42 commented Jun 15, 2026

Copy link
Copy Markdown
Member

This PR makes the Transfer to Spending amount screen fill in the maximum transferable amount when you try to enter a value above the cap, instead of only flashing an error toast.

Description

Previously, entering an amount above the spending maximum on the Transfer to Spending screen blocked the input and showed the "Spending Balance Maximum" toast while leaving the field unchanged. Now, when the cap is exceeded, the amount snaps to the current maximum allowed to send and the toast still appears, so it is a single step to continue with the largest possible transfer.

This ports the max-exceeded behavior from the iOS fix in synonymdev/bitkit-ios#595. The two-pass LSP max-client-balance clamping that the iOS PR also introduced already exists on Android in the transfer view model, so this change is limited to the input-snapping behavior.

Preview

Screen_recording_20260615_082049.webm

QA Notes

Manual Tests

  • 1. On-chain balance above the spending cap → Transfer → Spending Amount → type an amount above the maximum: input snaps to the maximum and the "Spending Balance Maximum" toast appears.
  • 2. regression: Spending Amount → tap MAX: amount fills to the maximum.
  • 3. regression: Spending Amount → tap 25%: amount is the quarter capped to the maximum.
  • 4. Spending Amount → amount at maximum → Continue: proceeds to the next step.

Automated Checks

  • Local: just compile passes.
  • CI: standard compile, unit test, and detekt checks run by the PR bot.

jvsena42 and others added 2 commits June 15, 2026 07:31
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f495670474

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment thread app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt Outdated
@greptile-apps

greptile-apps Bot commented Jun 15, 2026

Copy link
Copy Markdown

Greptile Summary

This PR ports the "snap to max on cap exceeded" behavior from iOS to Android. When the user types an amount above the spending cap on the Transfer to Spending screen (and on the Advanced screen), the input now snaps to the current maximum rather than being silently blocked. The quarter-amount capping logic is also moved from the UI layer into the ViewModel.

  • MaxExceeded snap: Both SpendingAmountScreen and SpendingAdvancedScreen now call amountInputViewModel.setSats(max, currentCurrencies) before showing the warning toast; rememberUpdatedState is correctly used for currentCurrencies in both screens so the currency state is always fresh inside the long-running LaunchedEffect.
  • quarterAmount in state: The 25% calculation is moved into estimateFinalMaxSendAmount in the ViewModel and stored as quarterAmount in TransferToSpendingUiState, removing the balanceAfterFeeQuarter() helper; the test is updated to assert the new field.
  • onClickMaxAmount / onClickQuarter simplification: Both UI callbacks are reduced to a single setSats call; the previous viewModel.updateLimits(amount) calls are removed on the assumption that SpendingAdvancedScreen re-derives transferValues from order.clientBalanceSat on mount.

Confidence Score: 4/5

Safe to merge for the primary happy path; the open question from the previous review thread about whether _transferValues stays consistent when the user reaches the advanced screen via the cap-snap path is the only thing worth verifying before merging.

The change is narrow and well-contained: two UI screens and one ViewModel. The currentCurrencies staleness fix is correctly applied with rememberUpdatedState in both screens. The main behavioral gap noted in the prior review thread — that the MaxExceeded snap path in SpendingAmountScreen does not call viewModel.updateLimits() — is still present and unaddressed. SpendingAdvancedScreen does re-derive transferValues via its own LaunchedEffect(order.clientBalanceSat), which may mitigate this in practice, but the alignment gap warrants a second look before merging.

The LaunchedEffect(Unit) MaxExceeded handler in SpendingAmountScreen.kt (around line 95) deserves a second look to confirm the missing updateLimits call is intentional given how SpendingAdvancedScreen re-initialises its state.

Important Files Changed

Filename Overview
app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt Adds MaxExceeded snap-to-max behavior with currentCurrencies fix; removes viewModel.updateLimits() from both MAX and quarter paths — the previous thread noted this gap in the MaxExceeded path specifically.
app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAdvancedScreen.kt Applies the same snap-to-max pattern for the advanced-screen cap; correctly uses currentCurrencies via rememberUpdatedState.
app/src/main/java/to/bitkit/viewmodels/TransferViewModel.kt Moves quarter-amount calculation into the ViewModel and exposes it as quarterAmount in state; removes the balanceAfterFeeQuarter() helper. The min(..., maxSend) guard on quarterAmount is mathematically redundant (25% ≤ 100%) but harmless.
app/src/test/java/to/bitkit/viewmodels/TransferViewModelTest.kt Adds an assertion for the new quarterAmount field; test coverage is proportionate to the ViewModel change.
changelog.d/next/1013.fixed.md Adds changelog entry for the fix; correctly placed in the next fragment directory.

Sequence Diagram

sequenceDiagram
    participant User
    participant SpendingAmountScreen
    participant AmountInputViewModel
    participant TransferViewModel

    User->>AmountInputViewModel: "types amount > max"
    AmountInputViewModel-->>SpendingAmountScreen: emit MaxExceeded effect
    SpendingAmountScreen->>AmountInputViewModel: setSats(currentMaxAllowedToSend, currentCurrencies)
    SpendingAmountScreen->>SpendingAmountScreen: show toast

    User->>SpendingAmountScreen: tap MAX button
    SpendingAmountScreen->>AmountInputViewModel: setSats(uiState.maxAllowedToSend, currencies)

    User->>SpendingAmountScreen: tap 25% button
    SpendingAmountScreen->>AmountInputViewModel: setSats(uiState.quarterAmount, currencies)
    Note over TransferViewModel: quarterAmount pre-computed in ViewModel

    User->>SpendingAmountScreen: tap Continue
    SpendingAmountScreen->>TransferViewModel: onConfirmAmount(sats)
Loading

Reviews (2): Last reviewed commit: "fix: stale currencies" | Re-trigger Greptile

Comment thread app/src/main/java/to/bitkit/ui/screens/transfer/SpendingAmountScreen.kt Outdated
@jvsena42 jvsena42 self-assigned this Jun 15, 2026
@jvsena42 jvsena42 marked this pull request as draft June 15, 2026 10:57
@jvsena42 jvsena42 marked this pull request as ready for review June 15, 2026 11:23
@jvsena42

Copy link
Copy Markdown
Member Author

I didn't implement on send flows because could cause issues on services that require exact amounts like Boltz if the user don't see that the amount was auto-capped

@jvsena42 jvsena42 requested a review from ovitrif June 15, 2026 13:19

@ovitrif ovitrif left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tAck

Very nice and intuitive, wanted to suggest this behavior for long time :)

@ovitrif

ovitrif commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Updated branch via github web app because an e2e shard reported failure already, so waiting was warranted anyways.

@ovitrif ovitrif enabled auto-merge June 15, 2026 17:15
@ovitrif ovitrif added this to the 2.4.0 milestone Jun 15, 2026
@ovitrif ovitrif merged commit cfcb2e6 into master Jun 15, 2026
17 checks passed
@ovitrif ovitrif deleted the fix/set-max-amount-transfer branch June 15, 2026 17:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants